/* DRW 15/07/05
I wrote this to try and demonstrate some very basic usage of Ricard's
blobslib for OpenCV, cvblobslib_OpenCV_v2.zip available at the 
OpenCV community site.

I have only be using C/C++ for two weeks, and OpenCV for half that. 
The code is almost certainly ugly so if anyone wants to rewrite it
PLEASE do!

It was written, built and run in Visual Studio 2003 .NET following 
the compilation and project setup instructions in the HOWTO Ricard has 
included as part of the latest release.

*/


// Include files
#include <stdlib.h>
// OpenCV
#include <OpenCV/cv.h>
#include <OpenCV/cxcore.h>
#include <OpenCV/highgui.h>
// Blobs
#include <Blob.h>
#include <BlobResult.h>


int main(int argc, char *argv[])
{
	// GENERATE AN IMAGE WITH BLOBS
	// delcare an image
	IplImage *img = 0;
	// initalise img as 640x480, 8bit, 1channel (i.e. greyscale)
	img = cvCreateImage(cvSize(640 ,480 ),IPL_DEPTH_8U,1);
	// make the image back
	cvSet(img, cvScalar(0));

	// make some blobs
	cvCircle( img, cvPoint(200 , 200 ), 10, CV_RGB(255, 255, 255), CV_FILLED, 1, 0);
	cvCircle( img, cvPoint(20 , 400 ), 4, CV_RGB(255, 255, 255), CV_FILLED, 1, 0);
	cvCircle( img, cvPoint(550 , 50 ), 25, CV_RGB(255, 255, 255), CV_FILLED, 1, 0);
	cvRectangle( img, cvPoint( 550, 420), cvPoint(  600,460  ),	CV_RGB(255, 255, 255), CV_FILLED, 8, 0);
	// FIND AND MARK THE BLOBS
	// delcare a set of blob results
	CBlobResult blobs;
	// get the blobs from the image, with no mask, using a threshold of 100
	blobs = CBlobResult( img, NULL, 100, true );
	blobs.Filter( blobs, B_INCLUDE, CBlobGetArea(), B_LESS, 5000 );// area <150
	blobs.Filter( blobs, B_INCLUDE, CBlobGetArea(), B_GREATER, 0 );// area <150
	// mark the blobs on the image
	int i;
	// delare a single blob
	CBlob Blob;
	// some vars
	int iMaxx, iMinx, iMaxy, iMiny, iMeanx, iMeany;
	// for each blob
	for  (i=0; i<blobs.GetNumBlobs(); ++i)
	{
		// get the blob info
		Blob = blobs.GetBlob(i);
		// get max, and min co-ordinates
		iMaxx=Blob.MaxX();
		iMinx=Blob.MinX();
		iMaxy=Blob.MaxY();
		iMiny=Blob.MinY();
		// find the average of the blob (i.e. estimate its centre)
		iMeanx=(iMinx+iMaxx)/2;
		iMeany=(iMiny+iMaxy)/2;
		// print blob info
		printf("%d (%d,%d)", i, iMeanx, iMeany);

		// get the blob Area
		CBlobGetArea getArea;
		double blobArea;
		blobArea = getArea( Blob);
		printf("\n\t\tArea: %.0f", blobArea);
		
		// get the distance from (50,100) - default (0,0)
		CBlobGetDistanceFromPoint getDist(0,0);
		double blobDist;
		blobDist = getDist(Blob);
		printf("\n\t\tDistance: %f", blobDist);

		// get blob centres
		CBlobGetXCenter getXc;
		CBlobGetYCenter getYc;
		double blobCentre[2];
		blobCentre[0] = getXc(Blob);
		blobCentre[1] = getYc(Blob);
		printf("\n\t\tCentre: (%.0f,%.0f)", blobCentre[0], blobCentre[1]);

		// get length & breadth of blob
		CBlobGetLength getL;
		CBlobGetBreadth getB;
		double blobL, blobB;
		blobL = getL(Blob);
		blobB = getB(Blob);
		printf("\n\t\t(Length,Breadth): (%.02f,%.02f)\tRatio: %.02f", blobL, blobB, blobL/blobB);

		// get moment of blob
		CBlobGetMoment getM00(0, 0), getM01(0, 1), getM10(1, 0);
		double blobM00, blobM01, blobM10;
		blobM00 = getM00(Blob);
		blobM01 = getM01(Blob);
		blobM10 = getM10(Blob);
		printf("\n\t\tMoments\n\t\t\t00: %.02f\n\t\t\t10: %.02f\n\t\t\t01: %.02f", blobM00, blobM10, blobM01);

		/* minor Axis does not work with blobslib v2.2 but is expected in next version
		// get major and minor axes
		CBlobGetMajorAxisLength getMajorAxis;
		CBlobGetMinorAxisLength getMinorAxis;
		double blobAxes[2], roundness;
		blobAxes[0] = getMajorAxis(Blob);
		blobAxes[1] = getMinorAxis(Blob);
		printf("\n\t\tAxes\n\t\t\tMajor: %.02f\n\t\t\tMinor: %.02f", blobAxes[0], blobAxes[1]);
		roundness = blobAxes[0]/blobAxes[1];
		printf("\n\t\t\tRatio: %.02f", roundness);*/
		


		// get ellipse
		CvBox2D Ellipse;
	    CvPoint2D32f blobCenter;  /* center of the box */
	    CvSize2D32f  blobSize;    /* box width and length */
		double ellipseCentre[2], ellipseAngle, ellipseWidth, ellipseHeight;

		Ellipse = Blob.GetEllipse();
		ellipseAngle = Ellipse.angle;
		ellipseCentre[0]=Ellipse.center.x;
		ellipseCentre[1]=Ellipse.center.y;
		ellipseHeight = Ellipse.size.height;
		ellipseWidth = Ellipse.size.width;

		printf("\n\t\tEllipse\n\t\t\tCentre: (%.02f,%.02f)\n\t\t\tAngle:%.02f\n\t\t\tSize: %.02fx%.02f", 
			ellipseCentre[0], ellipseCentre[1], ellipseAngle, ellipseHeight, ellipseWidth);
		// draw ellipse
		//cvEllipse( img, cvPointFrom32f(Ellipse.center), cvSize(Ellipse.size.height, Ellipse.size.width), 
		//	Ellipse.angle, 0, 360, CV_RGB(150, 150, 150), 1, 8, 0 );

		printf("\n");

		// mark centre
		cvLine( img, cvPoint(iMeanx, iMeany), cvPoint(iMeanx, iMeany), CV_RGB(50, 50 , 50), 4, 8, 0 );
		// mark box around blob
		cvRectangle( img, cvPoint(iMinx , iMiny ), cvPoint ( iMaxx, iMaxy ), CV_RGB(150, 150, 150), 1, 8, 0);
		
	}// each blob

	// display the image
	cvNamedWindow("image",1);
	cvShowImage("image", img);
	// keep image 'til keypress
	cvWaitKey(0);
	cvReleaseImage(&img);

	return 0;
}